home *** CD-ROM | disk | FTP | other *** search
/ InfoMagic Internet Tools 1993 July / Internet Tools.iso / RockRidge / mail / smail-3.1.28 / src / route.c < prev    next >
Encoding:
C/C++ Source or Header  |  1992-08-08  |  35.0 KB  |  1,307 lines

  1. /* @(#)src/route.c    1.19 8/8/92 19:29:42 */
  2.  
  3. /*
  4.  *    Copyright (C) 1987, 1988 Ronald S. Karr and Landon Curt Noll
  5.  *    Copyright (C) 1992  Ronald S. Karr
  6.  * 
  7.  * See the file COPYING, distributed with smail, for restriction
  8.  * and warranty information.
  9.  */
  10.  
  11. /*
  12.  * route.c:
  13.  *    Compute route to target hosts and fill in the transport,
  14.  *    next host and next address for a recipient address.
  15.  *
  16.  *    external functions: route_remote_addrs, verify_remote_addrs,
  17.  *                cache_routers, finish_routers,
  18.  *                match_end_domain, route_driver_finish,
  19.  *                find_router, find_route_driver,
  20.  *                read_router_file, read_method_file
  21.  */
  22.  
  23. #define NEED_SOCKETS
  24. #include <stdio.h>
  25. #include <ctype.h>
  26. #include <sys/types.h>
  27. #include <sys/stat.h>
  28. #include "defs.h"
  29. #include "smail.h"
  30. #include "route.h"
  31. #ifdef HAVE_BSD_NETWORKING
  32. #  define USE_MX_HINTS
  33. #  include "bindsmtpth.h"
  34. #endif /* HAVE_BSD_NETWORKING */
  35. #include "transport.h"
  36. #include "addr.h"
  37. #include "dys.h"
  38. #include "log.h"
  39. #include "exitcodes.h"
  40. #include "parse.h"
  41. #include "smailconf.h"
  42. #ifndef DEPEND
  43. # include "extern.h"
  44. # include "debug.h"
  45. # include "error.h"
  46. #endif
  47.  
  48. /* variables exported from this file */
  49. int cached_routers = FALSE;        /* TRUE if cache_routers() called */
  50.  
  51. /* functions local to this file */
  52. static void premunge_remote_addrs();
  53. static void compute_transport();
  54. static void compute_next_addr();
  55. static void next_addr_basic();
  56. static void next_addr_uucp();
  57. static char *route_to_route_addr();
  58. static char *rebuild_work_addr();
  59. static char *router_read_method();
  60. static char *router_driv_function();
  61.  
  62.  
  63. /*
  64.  * route_remote_addrs - route addrs to transport, next host and next_addr
  65.  */
  66. void
  67. route_remote_addrs(in, out, retry, defer, fail)
  68.     struct addr *in;            /* input local-form addrs */
  69.     struct addr **out;            /* output resolved addrs */
  70.     struct addr **retry;        /* addr structures to reparse */
  71.     struct addr **defer;        /* addrs to defer to a later time */
  72.     struct addr **fail;            /* unresolvable addrs */
  73. {
  74.     struct router *rp;            /* temp for stepping thru routers */
  75.     register struct addr *cur;        /* temp for stepping through addrs */
  76.     struct addr *next;            /* next value for cur */
  77.     struct transport_hints * hint;
  78. #ifdef USE_MX_HINTS
  79.     struct mx_transport_hint * mx_hint;
  80.     struct ipaddr_hint * a_hint;
  81. #endif /* USE_MX_HINTS */
  82.  
  83.     DEBUG(DBG_ROUTE_HI, "route_remote_addrs called\n");
  84.  
  85.     /* first munge the addr structure as required */
  86.     premunge_remote_addrs(in);
  87.  
  88.     /* sort addresses to simplify duplicate elimination by rtd_standard() */
  89.     in = addr_sort(in, OFFSET(addr, target));
  90.  
  91.     /*
  92.      * give the complete input list to each router in turn.
  93.      * router drivers must obey the rules about overriding
  94.      * of routes produced by previous routers.  At the end
  95.      * this routine will cleanup the addr structures.
  96.      */
  97.     for (rp = routers; rp; rp = rp->succ) {
  98.     struct addr *new_in;        /* addrs to put through next router */
  99.     /* look up the router driver by name */
  100.     struct route_driver *driver = find_route_driver(rp->driver);
  101.  
  102.     if (driver == NULL) {
  103.         /*
  104.          * ERR_109 - router driver not found
  105.          *
  106.          * DESCRIPTION
  107.          *      A driver name was not in the table of router drivers.
  108.          *
  109.          * ACTIONS
  110.          *      Defer all input addresses with configuration errors.
  111.          *      Since it cannot be known if this router would have
  112.          *      overridden previous routers, all input addresses must be
  113.          *      deferred.
  114.          *
  115.          * RESOLUTION
  116.          *      The postmaster must check the router configuration
  117.          *      before deliver can be performed.
  118.          */
  119.         insert_addr_list(in,
  120.                  defer,
  121.                  note_error(ERR_CONFERR|ERR_109,
  122.                     xprintf(
  123.                           "router %s: driver %s not found",
  124.                         rp->name,
  125.                         rp->driver)));
  126.         return;
  127.     }
  128.  
  129.     /* call the driver */
  130.     new_in = NULL;
  131.     (*driver->driver)(rp, in, &new_in, defer, fail);
  132.     in = new_in;
  133.     }
  134.  
  135.     /*
  136.      * now that all routers have had their chance we cleanup
  137.      * the input list to form the output list of resolved
  138.      * addresses, and note addresses that no router could
  139.      * route to.
  140.      */
  141.     for (cur = in; cur; cur = next) {
  142.     next = cur->succ;
  143.  
  144.     if (cur->match_count == -1 ||
  145.         (cur->flags & (ADDR_PARTLOCAL|ADDR_FULLMATCH)) == ADDR_PARTLOCAL)
  146.     {
  147.         /* no router could match the target, fail address */
  148.         exitvalue = EX_NOHOST;    /* set exit status */
  149.         /*
  150.          * ERR_101 - unknown host
  151.          *
  152.          * DESCRIPTION
  153.          *      The target in this addr structure was not matched by any
  154.          *      of the routers.
  155.          *
  156.          * ACTIONS
  157.          *      A message is sent to the owner of the address, or to the
  158.          *      sender if the address has no owner.
  159.          *
  160.          * RESOLUTION
  161.          *      The address owner or sender should determine the correct
  162.          *      domain name.  If the owner or sender believes the
  163.          *      message was in error, he or she should send mail to the
  164.          *      postmaster.
  165.          */
  166.         cur->error = note_error(ERR_NSOWNER|ERR_101, "unknown host");
  167.         cur->succ = *fail;
  168.         *fail = cur;
  169.         continue;
  170.     }
  171.     if (cur->next_host == NULL) {
  172.         /* routed to local host, reparse */
  173.         (void) strcpy(cur->work_addr, cur->remainder);
  174.         cur->flags &= ~(ADDR_FINISHED | ADDR_FULLMATCH);
  175.         cur->transport = NULL;
  176.         cur->tphint_list = NULL;
  177.         if (cur->route) {
  178.         xfree(cur->route);
  179.         cur->route = NULL;
  180.         }
  181.         cur->remainder = NULL;
  182.         cur->succ = *retry;
  183.         *retry = cur;
  184.         continue;
  185.     }
  186.     if (cur->transport == NULL) {
  187.         /* router did not compute a transport, we must */
  188.         compute_transport(cur);
  189.         if (cur->error && (cur->error->info & ERR_CONFERR)) {
  190.         /* defer configuration errors */
  191.         cur->succ = *defer;
  192.         *defer = cur;
  193.         continue;
  194.         }
  195.     }
  196.     if (cur->next_addr == NULL) {
  197.         compute_next_addr(cur);
  198.     }
  199.     if (cur->error) {
  200.         /* got an error, fail the address */
  201.         cur->succ = *fail;
  202.         *fail = cur;
  203.     } else {
  204.         /* link into the output queue if things went okay */
  205.         if (cur->next_host) {
  206.         DEBUG3(DBG_ROUTE_LO, "    routed %s --> %s at %s\n",
  207.                cur->in_addr, cur->next_addr, cur->next_host);
  208.         } else {
  209.         DEBUG2(DBG_ROUTE_LO,
  210.                "    routed %s --> %s on the local host\n",
  211.                cur->in_addr, cur->next_addr);
  212.         }
  213.         for (hint = cur->tphint_list; hint; hint = hint->succ) {
  214. #ifdef USE_MX_HINTS
  215.           if (EQ("mx",hint->hint_name))
  216.         {
  217.           mx_hint = (struct mx_transport_hint *) hint->private;
  218.           DEBUG3(DBG_ROUTE_LO,
  219.              "      transport hint %s %d %s\n", hint->hint_name,
  220.              mx_hint->preference,
  221.              mx_hint->exchanger);
  222.           for (a_hint = mx_hint->ipaddrs; a_hint; a_hint = a_hint->succ)
  223.             {
  224.               DEBUG2(DBG_ROUTE_LO,
  225.                  "        address hint %s %s\n",
  226.                  a_hint->hostname,inet_ntoa(a_hint->addr));
  227.             }
  228.         }
  229.           else
  230. #endif /* USE_MX_HINTS */
  231.         DEBUG1(DBG_ROUTE_LO,
  232.                "      transport hint %s\n", hint->hint_name);
  233.         }
  234.         cur->succ = *out;
  235.         *out = cur;
  236.     }
  237.     }
  238. }
  239.  
  240.  
  241. /*
  242.  * verify_remote_addrs - perform quick verify of remote addresses
  243.  *
  244.  * form a list of okay (verified) addrs, plus deferred (not currently
  245.  * determinable) addrs and failed (not deliverable) addrs.
  246.  */
  247. void
  248. verify_remote_addrs(in, okay, defer, fail)
  249.     struct addr *in;            /* input remote addr list */
  250.     struct addr **okay;            /* output list of verified addrs */
  251.     struct addr **defer;        /* temporariliy unverifiable addrs */
  252.     struct addr **fail;            /* unverified addrs */
  253. {
  254.     struct router *rp;            /* temp for stepping thru routers */
  255.     register struct addr *cur;        /* temp for stepping through addrs */
  256.  
  257.     DEBUG(DBG_ROUTE_HI, "verify_remote_addrs called\n");
  258.  
  259.     /* first munge the addr structure as required */
  260.     premunge_remote_addrs(in);
  261.  
  262.     /*
  263.      * give the complete input list to each router in turn.
  264.      * router drivers must obey the rules about overriding
  265.      * of routes produced by previous routers.  At the end
  266.      * this routine will cleanup the addr structures.
  267.      */
  268.     for (rp = routers; in && rp; rp = rp->succ) {
  269.     struct addr *retry;        /* addrs to put through next router */
  270.     /* look up the router driver by name */
  271.     struct route_driver *driver = find_route_driver(rp->driver);
  272.  
  273.     if (driver == NULL) {
  274.         /*
  275.          * ERR_109 - router driver not found
  276.          *
  277.          * DESCRIPTION
  278.          *      A driver name was not in the table of router drivers.
  279.          *
  280.          * ACTIONS
  281.          *      Defer all input addresses with configuration errors.
  282.          *      Since it cannot be known if this router would have
  283.          *      overridden previous routers, all input addresses must be
  284.          *      deferred.
  285.          *
  286.          * RESOLUTION
  287.          *      The postmaster must check the router configuration
  288.          *      before delivery can be performed.
  289.          */
  290.         insert_addr_list(in,
  291.                  defer,
  292.                  note_error(ERR_CONFERR|ERR_109,
  293.                     xprintf(
  294.                           "router %s: driver %s not found",
  295.                         rp->name,
  296.                         rp->driver)));
  297.         return;
  298.     }
  299.  
  300.     /* call the driver */
  301.     retry = NULL;
  302.     (*driver->verify)(rp, in, &retry, okay, defer, fail);
  303.     in = retry;
  304.     }
  305.  
  306.     /*
  307.      * some cleanup is required on the the addr list
  308.      */
  309.     for (cur = in; cur; cur = cur->succ) {
  310.     if (cur->flags&ADDR_PUTDOT) {
  311.         /* a dot was removed from the end of the target, put it back */
  312.         cur->target[strlen(cur->target)] = '.';
  313.     } else if (cur->flags&ADDR_MOVEDOT) {
  314.         /* move a dot back to the end of the target, from the front */
  315.         (void) strcpy(cur->target, cur->target + 1);
  316.         cur->target[strlen(cur->target)] = '.';
  317.     }
  318.     }
  319. }
  320.  
  321.  
  322. /*
  323.  * cache_routers - call cache entrypoints for all routers
  324.  *
  325.  * cache information used by router drivers.  This can be called when
  326.  * it is determined that there will be an attempt to deliver more than
  327.  * one mail message, to increase the overall efficiency of the mailer.
  328.  *
  329.  * Daemons can call this periodically to recache stale data.
  330.  */
  331. void
  332. cache_routers()
  333. {
  334.     struct router *rp;            /* temp for stepping thru routers */
  335.     struct route_driver *driver;
  336.  
  337.     for (rp = routers; rp; rp = rp->succ) {
  338.     driver = find_route_driver(rp->driver);
  339.     if (driver && driver->cache) {
  340.         (*driver->cache)(rp);
  341.     }
  342.     }
  343.     cached_routers = TRUE;
  344. }
  345.  
  346. #ifdef notyet
  347. /*
  348.  * finish_routers - free resources used by all routers
  349.  *
  350.  * free information that was cached by routers or used by routers in
  351.  * the process of routing.  Routers can cache data for efficiency, or
  352.  * can maintain state between invocations.  This function is called
  353.  * when routers will no longer be needed, allowing routers to free any
  354.  * resources that they were using that will no longer be needed.  For
  355.  * example, it is a good idea for routers to close any files that they
  356.  * opened, as file descriptors are a precious resource in some
  357.  * machines.
  358.  */
  359. void
  360. finish_routers()
  361. {
  362.     struct router *rp;            /* temp for stepping thru routers */
  363.     struct route_driver *driver;
  364.  
  365.     for (rp = routers; rp; rp = rp->succ) {
  366.     driver = find_route_driver(rp->driver);
  367.     if (driver && driver->finish) {
  368.         (*driver->finish)(rp);
  369.     }
  370.     }
  371.  
  372.     cached_routers = FALSE;
  373. }
  374. #endif
  375.  
  376.  
  377. /*
  378.  * premunge_remote_addrs - pre-routing munging on remote addr structures
  379.  *
  380.  * do a premunge on the target, by taking a dot at the end and
  381.  * putting it at the front (if one is not already at the front).
  382.  * Also, initialize the flags field, to remove any extraneously
  383.  * set flags.
  384.  */
  385. static void
  386. premunge_remote_addrs(list)
  387.     struct addr *list;            /* list of remote addrs to premunge */
  388. {
  389.     register struct addr *cur;        /* current address being processed */
  390.  
  391.     for (cur = list; cur; cur = cur->succ) {
  392.     register int len = strlen(cur->target);
  393.  
  394.     cur->flags &= ~(ADDR_PUTDOT |
  395.             ADDR_MOVEDOT |
  396.             ADDR_ERROR |
  397.             ADDR_FINISHED |
  398.             ADDR_FULLMATCH |
  399.             ADDR_NOTUSER |
  400.             ADDR_ISUSER);
  401.     cur->match_count = -1;
  402.     if (cur->target[len-1] == '.') {
  403.         if (cur->target[0] == '.') {
  404.         cur->target[len-1] = '\0';
  405.         cur->flags |= ADDR_PUTDOT;
  406.         } else {
  407.         /* have to move the target so that a dot can be inserted */
  408.         register char *p = cur->target;
  409.  
  410.         while (--len) {
  411.             p[len] = p[len - 1];
  412.         }
  413.         p[0] = '.';
  414.         cur->flags |= ADDR_MOVEDOT;
  415.         }
  416.     }
  417.     }
  418. }
  419.  
  420.  
  421. /*
  422.  * match_end_domain - try to match one of a list of domains against a target
  423.  *
  424.  * given a list of domains separated by colons, determine if the given
  425.  * target ends in one of those domains.  If so, return a pointer to the
  426.  * `.' that precedes the domain that matched, else return NULL.  The
  427.  * list is scanned from left to right, with the first match returned.
  428.  */
  429. char *
  430. match_end_domain(domains, target)
  431.     char *domains;            /* colon separated list of domains */
  432.     char *target;            /* target to test against */
  433. {
  434.     register char *cur;            /* current domain being checked */
  435.  
  436.     if (!domains)
  437.     return NULL;
  438.  
  439.     for (cur = strcolon(domains); cur; cur = strcolon((char *)NULL)) {
  440.     char *d = is_suffix(cur, target, TRUE);
  441.     if (d && d != target) {
  442.         return d - 1;
  443.     }
  444.     }
  445.  
  446.     /* did not end in one of the domains */
  447.     return NULL;
  448. }
  449.  
  450. /*
  451.  * is_suffix - try to match a domain against a target
  452.  *
  453.  * given a domain, determine if the given target ends in that domain.
  454.  * If so, return a pointer to the domain in the target, else NULL.
  455.  */
  456.  
  457. char *
  458. is_suffix(domain, target, proper_suffix)
  459.     char *domain;            /* domain name */
  460.     char *target;            /* target to test against */
  461.     int proper_suffix;            /* fail if target equals domain */
  462. {
  463.     int skip;
  464.  
  465.     if (*domain == '.')
  466.     domain++;
  467.     if (*domain == '\0')
  468.     return NULL;
  469.     skip = strlen(target) - strlen(domain);
  470.  
  471.     if (((skip == 0 && !proper_suffix) ||
  472.      (skip > 0 && target[skip - 1] == '.')) &&
  473.     EQIC(target + skip, domain))
  474.     {
  475.     return target + skip;
  476.     }
  477.  
  478.     return NULL;
  479. }
  480.  
  481. /*
  482.  * route_driver_finish - fill in addr structures for a route driver
  483.  *
  484.  * route drivers may call this routine for each addr structure they
  485.  * have computed a route to.  This routine completes the addr structure
  486.  * if it is determined that the computed route has precedence over any
  487.  * previously computed route.  In the case that the computed route has
  488.  * precedence over future routers, the ADDR_FINISHED flag is set in
  489.  * the addr.flags struct element.
  490.  */
  491. void
  492. route_driver_finish(rp, addr, match_count, next_host, route, transport, hints)
  493.     struct router *rp;            /* the calling router */
  494.     struct addr *addr;            /* addr structure in question */
  495.     int match_count;            /* target match count */
  496.     char *next_host;            /* computed next_host value */
  497.     char *route;            /* computed route value */
  498.     struct transport *transport;    /* optional transport from driver */
  499.     struct transport_hints *hints;    /* transport hints from driver */
  500. {
  501.     if (addr->flags&ADDR_FINISHED) {
  502.     /*
  503.      * a router erroneously found a new route for a finished addr,
  504.      * ignore it
  505.      */
  506.     return;
  507.     }
  508.  
  509.     /*
  510.      * consider this a match, if it matched more characters than
  511.      * any earlier router
  512.      */
  513.  
  514.     if (match_count > addr->match_count) {
  515.  
  516.     /*
  517.      * if the router matched the address completely, then
  518.      * consider the address to have been matched completely
  519.      */
  520.  
  521.     if (strlen(addr->target) == match_count ||
  522.         (addr->target[0] == '.' &&
  523.          strlen(addr->target) == match_count - 1))
  524.     {
  525.         addr->flags |= ADDR_FINISHED|ADDR_FULLMATCH;
  526.     } else {
  527.         if (next_host == NULL) {
  528.  
  529.         /*
  530.          * the local host cannot be matched partially, so
  531.          * ignore any attempts to do so
  532.          */
  533.  
  534.         return;
  535.         }
  536.         if (rp->flags&USE_ALWAYS) {
  537.         addr->flags |= ADDR_FINISHED;
  538.         }
  539.     }
  540.  
  541.     /*
  542.      * this route has precedence over previous routes
  543.      */
  544.  
  545.     addr->router = rp;
  546.     addr->match_count = match_count;
  547.     if (addr->next_host) {
  548.         xfree(addr->next_host);
  549.     }
  550.     if (next_host) {
  551.         addr->next_host = COPY_STRING(next_host);
  552.     } else {
  553.         addr->next_host = NULL;
  554.     }
  555.     if (addr->route) {
  556.         xfree(addr->route);
  557.     }
  558.     if (route) {
  559.         addr->route = COPY_STRING(route);
  560.     } else {
  561.         addr->route = NULL;
  562.     }
  563.     addr->transport = transport;
  564.     addr->tphint_list = hints;
  565.     if (addr->next_addr) {
  566.         /*
  567.          * cleanup after a previous router that computed the
  568.          * next_addr itself
  569.          */
  570.         xfree(addr->next_addr);
  571.         addr->next_addr = NULL;
  572.     }
  573.     if (next_host) {
  574.         DEBUG3(DBG_ROUTE_LO, "%s: %s matched by %s:\n",
  575.            addr->in_addr, addr->target, addr->router->name);
  576.     } else {
  577.         DEBUG3(DBG_ROUTE_LO, "%s: reparse address %s generated by %s:\n",
  578.            addr->in_addr, addr->remainder, addr->router->name);
  579.     }
  580.     }
  581. }
  582.  
  583. /*
  584.  * compute_next_addr - compute the next_addr for a routed recipient address
  585.  */
  586. static void
  587. compute_next_addr(addr)
  588.     struct addr *addr;            /* address to be completed */
  589. {
  590.     char *r_route;
  591.  
  592.     if (addr->error) {
  593.     /* ignore the addr if it already has a pending error condition */
  594.     return;
  595.     }
  596.  
  597.     if (addr->flags&ADDR_PUTDOT) {
  598.     /* a dot was removed from the end of the target, put it back */
  599.     addr->target[strlen(addr->target)] = '.';
  600.     } else if (addr->flags&ADDR_MOVEDOT) {
  601.     /* move a dot back to the end of the target, from the front */
  602.     (void) strcpy(addr->target, addr->target+1);
  603.     addr->target[strlen(addr->target)] = '.';
  604.     }
  605.  
  606.     if (! (addr->flags & ADDR_FULLMATCH)) {
  607.  
  608.     /*
  609.      * if the target was not matched completely, append the
  610.      * target to the route.
  611.      */
  612.  
  613.     if (addr->route) {
  614.         r_route = xprintf("%s!%s", addr->route, addr->target);
  615.         xfree(addr->route);
  616.     } else {
  617.         r_route = COPY_STRING(addr->target);
  618.     }
  619.     addr->route = r_route;
  620.     }
  621.  
  622.     /*
  623.      * select a method for transforming the remainder/route/next_host
  624.      * triplet into a next_addr.  Default is method suitable for the
  625.      * inter-smail communication, but that's about it.
  626.      */
  627.  
  628.     if (addr->transport->flags & RT_NOXFORM) {
  629.     if (addr->route) {
  630.         r_route = route_to_route_addr(addr->route);
  631.         addr->next_addr = xprintf("%s:%s", r_route, addr->remainder);
  632.     } else {
  633.         addr->next_addr = COPY_STRING(addr->remainder);
  634.     }
  635.     }
  636.     if (addr->transport->flags & UUCP_XFORM) {
  637.     next_addr_uucp(addr);
  638.     } else if (addr->transport->flags & INET_XFORM) {
  639.     next_addr_basic(addr, TRUE);
  640.     } else {
  641.     next_addr_basic(addr, FALSE);
  642.     }
  643.     return;
  644. }
  645.  
  646. /*
  647.  * next_addr_basic - compute a next_addr for a basic transport
  648.  *
  649.  * This transformation leaves the address alone to the greatest extent
  650.  * possible, and makes an effort to do transformations that work well
  651.  * in environments with mixed-zone (sendmail and smail3) mailers.
  652.  *
  653.  * If the inet flag is TRUE, then the address will be left conformant
  654.  * to RFC822 and RFC1123.  However, routes will be included in
  655.  * route-addr notation.
  656.  */
  657. static void
  658. next_addr_basic(addr, inet)
  659.     struct addr *addr;
  660.     int inet;
  661. {
  662.     char *route = addr->route;
  663.     char *remainder = addr->remainder;
  664.     char *target = addr->target;
  665.     char *next_host = addr->next_host;
  666.     char *error;
  667.     int pflags;
  668.     char *r_route, *r_last;
  669.     char *p;
  670.     int c;
  671.  
  672.     /*
  673.      * try to rebuild the original address, or at least keep the
  674.      * spirit of the original address form, if a route is needed.
  675.      */
  676.  
  677.     switch (addr->flags & ADDR_FORM_MASK) {
  678.     case RFC_ROUTE:
  679.     case RFC_ENDROUTE:
  680.  
  681.     /*
  682.      * For route-addrs, if no additional route is needed for
  683.      * delivery to the final destination, then just use the
  684.      * remainder of the route; otherwise, build an RFC822-style
  685.      * route out of the needed additional route.
  686.      */
  687.  
  688.     if (route == NULL)
  689.         addr->next_addr = COPY_STRING(remainder);
  690.     else {
  691.         r_route = route_to_route_addr(route);
  692.         if ((addr->flags & ADDR_FORM_MASK) == RFC_ENDROUTE)
  693.         addr->next_addr = xprintf("%s:%s", r_route, remainder);
  694.         else
  695.         addr->next_addr = xprintf("%s,%s", r_route, remainder);
  696.         xfree(r_route);
  697.     }
  698.     return;
  699.  
  700.     case MAILBOX:
  701.  
  702.     /*
  703.      * for mailbox (user@host) addresses, get back the original
  704.      * address if there is no further routing; otherwise generate
  705.      * a mailbox address for a one-hop route; otherwise use RFC822
  706.      * route-addrs for routing (inet) or !-style routes (non-inet)
  707.      * if possible.
  708.      */
  709.  
  710.     pflags = addr->parseflags;
  711.     switch (parse_address(remainder, (char *)0, (char *)0, &pflags)) {
  712.     case MAILBOX:
  713.  
  714.         /*
  715.          * if the remainder is also a mailbox (which is actually
  716.          * an illegal form within a mailbox) then just send it if
  717.          * no further routing is needed; otherwise, make a
  718.          * route-addr or !-route out of it
  719.          */
  720.  
  721.         if (route == NULL)
  722.         addr->next_addr = COPY_STRING(remainder);
  723.         else {
  724.         if (inet) {
  725.             r_route = route_to_route_addr(route);
  726.             addr->next_addr = xprintf("%s:%s", r_route, remainder);
  727.             xfree(r_route);
  728.         } else {
  729.             p = build_partial_uucp_route(remainder,
  730.                 &error, addr->parseflags);
  731.             addr->next_addr = xprintf("%s!%s", route, p);
  732.         }
  733.         }
  734.         return;
  735.  
  736.     case PCT_MAILBOX:
  737.         if (route && mixed_address(remainder)) {
  738.         inet = TRUE;
  739.         break;
  740.         }
  741.         break;
  742.     }
  743.     if (route && strchr(route, '!') == NULL) {
  744.         addr->next_addr = xprintf("%s@%s", remainder, route);
  745.     } else if (route && inet) {
  746.         r_route = route_to_route_addr(route);
  747.         r_last = strrchr(r_route, ',');
  748.         if (r_last) {
  749.         *r_last++ = '\0';
  750.         r_last++;
  751.         addr->next_addr =
  752.             xprintf("%s:%s@%s", r_route, remainder, r_last);
  753.         } else {
  754.         addr->next_addr = xprintf("%s@%s", remainder, r_route + 1);
  755.         }
  756.         xfree(r_route);
  757.     } else if (route) {
  758.         addr->next_addr = xprintf("%s!%s", route, remainder);
  759.     } else {
  760.         addr->next_addr = xprintf("%s@%s", remainder, next_host);
  761.     }
  762.     return;
  763.  
  764.     case UUCP_ROUTE:
  765.     case BERKENET:
  766.     case DECNET:
  767.     if (inet) {
  768.         if (route && strchr(route, '!') == NULL) {
  769.         addr->next_addr = xprintf("%s@%s", remainder, route);
  770.         } else if (route) {
  771.         r_route = route_to_route_addr(route);
  772.         r_last = strrchr(r_route, ',');
  773.         if (r_last) {
  774.             *r_last++ = '\0';
  775.             r_last++;
  776.             addr->next_addr =
  777.             xprintf("%s:%s@%s", r_route, remainder, r_last);
  778.         } else {
  779.             addr->next_addr = xprintf("%s@%s", remainder, r_route + 1);
  780.         }
  781.         xfree(r_route);
  782.         } else {
  783.         addr->next_addr = xprintf("%s@%s", remainder, next_host);
  784.         }
  785.     } else {
  786.         if (route)
  787.         addr->next_addr = xprintf("%s!%s", route, remainder);
  788.         else
  789.         addr->next_addr = COPY_STRING(remainder);
  790.     }
  791.     return;
  792.  
  793.     case PCT_MAILBOX:
  794.  
  795.     /*
  796.      * for user%foo addresses, keep in mind that RFC1123 may prove
  797.      * a problem if we need to add a route.  To manage this we do
  798.      * one of two things: keep the user%foo form or change it to
  799.      * a mailbox address of some kind.  What we do depends on the
  800.      * mixing of % and ! operators.  Mixed addresses and Internet
  801.      * conformant addresses are sent out as @route:user@foo, where
  802.      * the route is formed using RFC822 route syntax; otherwise,
  803.      * we use route!user%foo.
  804.      */
  805.  
  806.     if (route == NULL)
  807.         addr->next_addr = xprintf("%s@%s", remainder, next_host);
  808.     else if (strchr(route, '!') == NULL) {
  809.         addr->next_addr = xprintf("%s@%s", remainder, route);
  810.     } else {
  811.         if (mixed_address(remainder) || inet) {
  812.         r_route = route_to_route_addr(route);
  813.         r_last = strrchr(r_route, ',');
  814.         if (r_last) {
  815.             *r_last++ = '\0';
  816.             r_last++;
  817.             addr->next_addr =
  818.             xprintf("%s:%s@%s", r_route, remainder, r_last);
  819.         } else {
  820.             addr->next_addr = xprintf("%s@%s", remainder, r_route + 1);
  821.         }
  822.         xfree(r_route);
  823.         } else {
  824.         addr->next_addr = xprintf("%s!%s", route, remainder);
  825.         }
  826.     }
  827.     return;
  828.  
  829.     default:
  830.  
  831.     /*
  832.      * we should never reach here, since that is the end of the
  833.      * addressing forms that can be encountered here.  Log it
  834.      * and send as UUCP-style address.
  835.      */
  836.  
  837.     write_log(LOG_PANIC, "internal error: next_addr_local: unknown form: in_addr:%s target:%s remainder:%s",
  838.           addr->in_addr, target, remainder);
  839.  
  840.     if (route)
  841.         addr->next_addr = xprintf("%s!%s", route, remainder);
  842.     else
  843.         addr->next_addr = COPY_STRING(remainder);
  844.     return;
  845.     }
  846. }
  847.  
  848. /*
  849.  * next_addr_uucp - compute a next_addr appropriate for uucp
  850.  *
  851.  * Compute the next_addr by concatenating the route and remainder
  852.  * into a !-style address.  Any % operators in the remainder will
  853.  * be left alone.  Other operators will be left alone.  However,
  854.  * if the input address contained mixed-operators, including all
  855.  * three of !-%-@, and we have to prepend a route, then remove all %
  856.  * operators.  This last point is necessary to avoid ambiguities
  857.  * between RFC1123 and RFC976 sites.
  858.  */
  859. static void
  860. next_addr_uucp(addr)
  861.     struct addr *addr;
  862. {
  863.     char *route = addr->route;
  864.     char *remainder = addr->remainder;
  865.     char *target = addr->target;
  866.     char *error;
  867.     char *r_route;
  868.  
  869.     if (route && switch_percent_and_bang &&
  870.     addr->parseflags & FOUND_MAILBOX &&
  871.     mixed_address(remainder))
  872.     {
  873.     r_route = build_uucp_route(remainder, &error, addr->parseflags);
  874.     } else {
  875.     r_route = build_partial_uucp_route(remainder, &error, addr->parseflags);
  876.     }
  877.     if (r_route == NULL) {
  878.     /* build_partial_uucp_route failed, fail the address */
  879.     /*
  880.      * ERR_108 - error building path
  881.      *
  882.      * DESCRIPTION
  883.      *      build_partial_uucp_route() returned an error while
  884.      *      attempting to build a UUCP-path from the remainder in
  885.      *      the address.  The specific error was returned in
  886.      *      `error'.
  887.      *
  888.      * ACTIONS
  889.      *      Notify the sender or the owner of the address of the
  890.      *      problem.
  891.      *
  892.      * RESOLUTION
  893.      *      The sender or owner should correct the supplied address
  894.      *      to use acceptible addressing forms.
  895.      */
  896.     addr->error =
  897.         note_error(ERR_NSOWNER|ERR_108,
  898.                xprintf("error building path: %s", error));
  899.     exitvalue = EX_DATAERR;    /* set the exit status */
  900.     return;
  901.     }
  902.  
  903.     /*
  904.      * build the next_addr by appending the remainder to the route
  905.      */
  906.  
  907.     if (route) {
  908.     addr->next_addr = xprintf("%s!%s", route, r_route);
  909.     xfree(r_route);
  910.     } else {
  911.     addr->next_addr = r_route;
  912.     }
  913.  
  914.     return;
  915. }
  916.  
  917. static char *
  918. route_to_route_addr(p)
  919.     char *p;
  920. {
  921.     struct str str;
  922.     int c;
  923.  
  924.     STR_INIT(&str);
  925.     STR_NEXT(&str, '@');
  926.     while (c = *p++) {
  927.     if (c == '!') {
  928.         STR_NEXT(&str, ',');
  929.         STR_NEXT(&str, '@');
  930.     } else {
  931.         STR_NEXT(&str, c);
  932.     }
  933.     }
  934.     STR_NEXT(&str, '\0');
  935.     STR_DONE(&str);
  936.  
  937.     return str.p;
  938. }
  939.  
  940. /*
  941.  * compute_transport - compute the transport from any available defaults
  942.  *
  943.  * some router drivers do not assign transports themselves but rely
  944.  * on defaults in the router structure.  These defaults can either be
  945.  * a single default transport or a table of transports associated with
  946.  * host names, where the special name `*' is a catchall.
  947.  */
  948. static void
  949. compute_transport(addr)
  950.     struct addr *addr;
  951. {
  952.     struct router *rp = addr->router;
  953.  
  954.     DEBUG2(DBG_ROUTE_HI, "compute_transport called: host=%s, router=%s\n",
  955.        addr->next_host, rp->name);
  956.     /* no transport yet assigned, look around for defaults */
  957.     if (rp->method) {
  958.     /* there is a "method", table of possible transports */
  959.     struct method *mp;
  960.  
  961.     mp = rp->method;
  962.     while (mp->host) {
  963.         if ((EQIC(addr->next_host, mp->host) || EQ(mp->host, "*")) &&
  964.           (mp->mingrade < 0 ||
  965.            (msg_grade >= mp->mingrade && msg_grade <= mp->maxgrade)))
  966.         {
  967.         /* found the right transport, use it */
  968.         addr->transport = find_transport(mp->transport);
  969.         if (addr->transport == NULL) {
  970.             /* configuration error, the transport does not exist */
  971.             /*
  972.              * ERR_102 - method transport not found
  973.              *
  974.              * DESCRIPTION
  975.              *      The transport to be used for the method was not
  976.              *      found in the table of transports.
  977.              *
  978.              * ACTIONS
  979.              *      Defer the message as a configuration error.
  980.              *
  981.              * RESOLUTION
  982.              *      The postmaster needs to correct the eror in the
  983.              *      method file.
  984.              */
  985.             addr->error = note_error(ERR_CONFERR|ERR_102,
  986.                          xprintf(
  987.             "router %s: method transport %s not found for host %s",
  988.                              rp->name,
  989.                              mp->transport,
  990.                              mp->host));
  991.             return;
  992.         }
  993.  
  994.         DEBUG2(DBG_ROUTE_MID, "use transport %s for %s\n",
  995.                addr->transport->name, addr->in_addr);
  996.         return;
  997.         }
  998.         mp++;
  999.     }
  1000.     }
  1001.  
  1002.     if (rp->default_transport) {
  1003.     /* there is a default, use it */
  1004.     addr->transport = find_transport(rp->default_transport);
  1005.     if (addr->transport == NULL) {
  1006.         /*
  1007.          * ERR_103 - default transport not found
  1008.          *
  1009.          * DESCRIPTION
  1010.          *      The default transport for the matching router is not in the
  1011.          *      list of transports.
  1012.          *
  1013.          * ACTIONS
  1014.          *      Defer the message as a configuration error.
  1015.          *
  1016.          * RESOLUTION
  1017.          *      The postmaster should correct the router file.
  1018.          */
  1019.         addr->error = note_error(ERR_CONFERR|ERR_103,
  1020.                      xprintf(
  1021.                    "router %s: default transport %s not found",
  1022.                          rp->name,
  1023.                          rp->default_transport));
  1024.         return;
  1025.     }
  1026.  
  1027.     DEBUG2(DBG_ROUTE_MID, "use default transport %s for %s\n",
  1028.            addr->transport->name, addr->in_addr);
  1029.     return;
  1030.     } else {
  1031.     /*
  1032.      * ERR_110 - no transport for router
  1033.      *
  1034.      * DESCRIPTION
  1035.      *      No method or default transport was given for the router that
  1036.      *      produced this address.
  1037.      *
  1038.      * ACTIONS
  1039.      *      Defer the address as a configuration error.
  1040.      *
  1041.      * RESOLUTION
  1042.      *      The postmaster must check the router configuration before
  1043.      *      delivery to the address can be performed.
  1044.      */
  1045.     addr->error = note_error(ERR_CONFERR|ERR_110,
  1046.                  xprintf("router %s: no transport found",
  1047.                      rp->name));
  1048.     }
  1049. }
  1050.  
  1051.  
  1052. /*
  1053.  * find_router - given a router's name, return the router structure
  1054.  *
  1055.  * return NULL if no router of that name exists.
  1056.  */
  1057. struct router *
  1058. find_router(name)
  1059.     register char *name;        /* search key */
  1060. {
  1061.     register struct router *rp;        /* temp for stepping thru routers */
  1062.  
  1063.     /* loop through all the routers */
  1064.     for (rp = routers; rp; rp = rp->succ) {
  1065.     if (EQ(rp->name, name)) {
  1066.         /* found the router in question */
  1067.         return rp;
  1068.     }
  1069.     }
  1070.  
  1071.     return NULL;            /* router not found */
  1072. }
  1073.  
  1074. /*
  1075.  * find_route_driver - given a driver's name, return the driver structure
  1076.  *
  1077.  * return NULL if driver does not exist.
  1078.  */
  1079. struct route_driver *
  1080. find_route_driver(name)
  1081.     register char *name;        /* search key */
  1082. {
  1083.     register struct route_driver *rdp;    /* pointer to table of drivers */
  1084.  
  1085.     for (rdp = route_drivers; rdp->name; rdp++) {
  1086.     if (EQ(rdp->name, name)) {
  1087.         return rdp;            /* found the driver */
  1088.     }
  1089.     }
  1090.  
  1091.     return NULL;            /* driver not found */
  1092. }
  1093.  
  1094.  
  1095. /*
  1096.  * read_router_file - read router file
  1097.  *
  1098.  * read the router file and build a router list describing the
  1099.  * entries.  Return an error message or NULL.
  1100.  */
  1101. char *
  1102. read_router_file()
  1103. {
  1104.     FILE *f;                /* open router file */
  1105.     char *error;            /* error from read_standard_file() */
  1106.     struct stat statbuf;
  1107.     static struct attr_table router_generic[] = {
  1108.     { "driver", t_string, NULL, NULL, OFFSET(router, driver) },
  1109.     { "transport", t_string, NULL, NULL,
  1110.       OFFSET(router, default_transport) },
  1111.     { "method", t_proc, NULL, (tup *)router_read_method, 0 },
  1112.     { "always", t_boolean, NULL, NULL, USE_ALWAYS },
  1113.     };
  1114.     struct attr_table *end_router_generic = ENDTABLE(router_generic);
  1115.     static struct router router_template = {
  1116.     NULL,                /* name */
  1117.     "pathalias",            /* driver, a reasonable default */
  1118.     NULL,                /* succ will be assigned */
  1119.     0,                /* flags */
  1120.     NULL,                /* method */
  1121.     NULL,                /* default_transport */
  1122.     NULL,                /* private */
  1123.     };
  1124.  
  1125.     /*
  1126.      * try to open router file, note file stat if possible
  1127.      */
  1128.     if (router_file == NULL || EQ(router_file, "-")) {
  1129.     return NULL;
  1130.     }
  1131.     f = fopen(router_file, "r");
  1132.     if (f == NULL) {
  1133.     if (require_configs) {
  1134.         return xprintf("%s: %s", router_file, strerrno());
  1135.     }
  1136.  
  1137.     add_config_stat(router_file, (struct stat *)NULL);
  1138.     return NULL;
  1139.     }
  1140.  
  1141.     (void)fstat(fileno(f), &statbuf);
  1142.     add_config_stat(router_file, &statbuf);
  1143.  
  1144.     /* call read_standard_file to do the real work */
  1145.     error = read_standard_file(f,
  1146.                    (char *)&router_template,
  1147.                    sizeof(struct router),
  1148.                    OFFSET(router, name),
  1149.                    OFFSET(router, flags),
  1150.                    OFFSET(router, succ),
  1151.                    router_generic,
  1152.                    end_router_generic,
  1153.                    router_driv_function,
  1154.                    (char **)&routers);
  1155.  
  1156.     /* finish up */
  1157.     (void) fclose(f);
  1158.  
  1159.     /* return any error message */
  1160.     if (error) {
  1161.     return xprintf("%s: %s", router_file, error);
  1162.     }
  1163.     return NULL;
  1164. }
  1165.  
  1166. /*
  1167.  * router_read_method - handle method attribute for routers
  1168.  *
  1169.  * the method attribute specifies a file which contains a method table
  1170.  * associating hosts with transports.  Use of this attribute causes
  1171.  * the table to be read and turned into an in-core method table.
  1172.  */
  1173. static char *
  1174. router_read_method(struct_p, attr)
  1175.     char *struct_p;            /* passed router structure */
  1176.     struct attribute *attr;        /* parsed attribute */
  1177. {
  1178.     struct router *rp = (struct router *)struct_p;
  1179.     char *error;
  1180.  
  1181.     if (attr->value == off) {
  1182.     rp->method = NULL;
  1183.     } else if (attr->value == on) {
  1184.     return xprintf("%s: boolean form for non-boolean attribute",
  1185.                attr->name);
  1186.     } else {
  1187.     int free_method_fn = FALSE;
  1188.     char *method_fn = attr->value;
  1189.  
  1190.     if (method_fn[0] != '/') {
  1191.         if (method_dir == NULL) {
  1192.         return xprintf("%s: %s not absolute and no method_dir",
  1193.                    attr->name, method_fn);
  1194.         }
  1195.         method_fn = xmalloc(strlen(method_dir) + strlen(method_fn) +
  1196.                 sizeof("/"));
  1197.         (void) sprintf(method_fn, "%s/%s", method_dir, attr->value);
  1198.         free_method_fn = TRUE;
  1199.     }
  1200.     rp->method = read_method_file(method_fn, &error);
  1201.  
  1202.     if (rp->method == NULL) {
  1203.         return xprintf("%s %s: %s", attr->name, attr->value, error);
  1204.     }
  1205.  
  1206.     if (free_method_fn) {
  1207.         xfree(method_fn);
  1208.     }
  1209.     }
  1210.  
  1211.     /* everything went okay */
  1212.     return NULL;
  1213. }
  1214.  
  1215. /*
  1216.  * read_method_file - read a method file and return an in-core method table
  1217.  *
  1218.  * return NULL if the method file could not be opened.
  1219.  */
  1220. struct method *
  1221. read_method_file(fn, error)
  1222.     char *fn;                /* name of method file */
  1223.     char **error;            /* store error message here */
  1224. {
  1225.     FILE *f = fopen(fn, "r");
  1226.     struct method *methods;        /* method table */
  1227.     int ct = 0;                /* count of methods */
  1228.     char *entry;            /* text of file entry */
  1229.     char *mgrade;            /* restricted grades for this method */
  1230.     struct stat statbuf;
  1231.  
  1232.     if (f == NULL) {
  1233.     *error = xprintf("open failed: %s", strerrno());
  1234.     return NULL;
  1235.     }
  1236.  
  1237.     (void)fstat(fileno(f), &statbuf);
  1238.     add_config_stat(fn, &statbuf);
  1239.  
  1240.     /* allocate space for at least the ending record */
  1241.     methods = (struct method *)xmalloc(sizeof(*methods));
  1242.  
  1243.     /* loop and read all of the table entries in the method file */
  1244.     while (entry = read_entry(f)) {
  1245.     char *error;
  1246.     struct attribute *new;
  1247.  
  1248.     new = parse_table(entry, &error);
  1249.     if (new == NULL) {
  1250.         return NULL;
  1251.     }
  1252.     methods = (struct method *)
  1253.         xrealloc((char *)methods, (ct + 2)*sizeof(*methods));
  1254.     methods[ct].host = new->name;
  1255.     methods[ct].mingrade = -1;
  1256.     methods[ct].maxgrade = -1;
  1257.     methods[ct].transport = new->value;
  1258.     mgrade = strchr(new->name, '/');
  1259.     if (mgrade != NULL) {
  1260.         *mgrade++ = '\0';
  1261.         if (isalnum(mgrade[0])) {
  1262.         methods[ct].mingrade = mgrade[0];
  1263.         methods[ct].maxgrade = mgrade[0];
  1264.         }
  1265.         if (mgrade[1] == '-') {
  1266.         if (isalnum(mgrade[2])) {
  1267.              methods[ct].maxgrade = mgrade[2];
  1268.         } else {
  1269.              methods[ct].maxgrade = 255;
  1270.         }
  1271.         if (methods[ct].mingrade == -1)
  1272.              methods[ct].mingrade = 0;
  1273.         }
  1274.     }
  1275.     ct++;
  1276.     }
  1277.  
  1278.     /* zero out the ending record */
  1279.     methods[ct].host = NULL;
  1280.     methods[ct].transport = NULL;
  1281.  
  1282.     return methods;
  1283. }
  1284.  
  1285. static char *
  1286. router_driv_function(struct_p, driver_attrs)
  1287.     char *struct_p;            /* passed router structure */
  1288.     struct attribute *driver_attrs;    /* driver-specific attributes */
  1289. {
  1290.     struct router *rp = (struct router *)struct_p;
  1291.     struct route_driver *drv;
  1292.  
  1293.     if (rp->driver == NULL) {
  1294.     return xprintf("router %s: no driver attribute", rp->name);
  1295.     }
  1296.     drv = find_route_driver(rp->driver);
  1297.     if (drv == NULL) {
  1298.     return xprintf("router %s: unknown driver: %s",
  1299.                rp->name, rp->driver);
  1300.     }
  1301.     if (drv->builder) {
  1302.     return (*drv->builder)(rp, driver_attrs);
  1303.     }
  1304.  
  1305.     return NULL;
  1306. }
  1307.